﻿using System.Collections.Generic;
using System.Data;
using System.Linq;
using viBook.Common;
using viBook.Models;

namespace viBook.Repositories
{
    public class CategoryRepository : ICategoryRepository
    {
        private readonly viBookContext _context = new viBookContext();


        public CategoryRepository()
        {
            _context = new viBookContext();
        }

        #region ICategoryRepository Members

        public IQueryable<Category> All
        {
            get
            {
                IQueryable<Category> result = _context.Categories;
                foreach (var category in result)
                {
                    category.NumberOfBook = _context.Books.Where(b => b.CategoryId == category.Id).Count();
                }
                return result;
            }
        }

        public Category Find(int id)
        {
            return _context.Categories.Find(id);
        }

        public void InsertOrUpdate(Category category)
        {
            if (category.Id == 0)
            {
                _context.Categories.Add(category);
            }
            else
            {
                _context.Entry(category).State = EntityState.Modified;
            }
            Save();
        }

        public bool Delete(int id)
        {
            Category category = FindCategoryWithAllBooks(id);
            if (category.ListBook.Count > 0)
            {
                return false;
            }
            _context.Categories.Remove(category);
            Save();
            return true;
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public IEnumerable<string> FindCategories(string criteria, int limit)
        {
            return _context.Categories.
                Where(c => c.CategoryName.ToLower().Contains(criteria.ToLower())).
                Take(limit).
                Select(c => c.CategoryName);
        }

        public IEnumerable<Category>
            GetAllCategories()
        {
            var allCategories = _context.Categories.ToList();
            foreach (var category in allCategories)
            {
                if (category != null)
                {
                    category.ListBook = new List<Book>();
                    var listBook =
                        _context.Books.Where(b => b.CategoryId == category.Id && b.IsBlocked==false).OrderBy(b => b.UploadedDate).Take(
                            Constant.MaximunBookPerPage).ToList();
                    if (listBook.Count() != 0)
                    {
                        foreach (var book in listBook)
                        {
                            book.NumberOfLikes = _context.BookLikes.Where(bl => bl.BookId == book.Id).ToList().Count();
                            book.NumberOfComments =
                                _context.BookComments.Where(bc => bc.BookId == book.Id).ToList().Count();
                            book.Uploader = _context.Users.Where(u => u.Id == book.UploadedBy).FirstOrDefault();
                            if (book.Uploader != null)
                            {
                                book.UploaderName = book.Uploader.DisplayName;
                                book.UploaderAvartar = book.Uploader.AvatarUrl;
                            }
                        }
                        category.ListBook = listBook;
                        category.NumberOfBook = category.ListBook.Count;
                    }
                }
            }
            return allCategories.Where(c => c.NumberOfBook != 0);
        }

        public Category FindCategoryWithAllBooks(int id)
        {
            var category = _context.Categories.Find(id);
            if (category != null)
            {
                var listBook = _context.Books.Where(b => b.CategoryId == category.Id && b.IsBlocked==false).ToList();
                foreach (var book in listBook)
                {
                    book.NumberOfLikes = _context.BookLikes.Where(bl => bl.BookId == book.Id).ToList().Count();
                    book.NumberOfComments = _context.BookComments.Where(bc => bc.BookId == book.Id).ToList().Count();
                    book.Uploader = _context.Users.Where(u => u.Id == book.UploadedBy).FirstOrDefault();
                    if (book.Uploader != null)
                    {
                        book.UploaderName = book.Uploader.DisplayName;
                        book.UploaderAvartar = book.Uploader.AvatarUrl;
                    }
                }
                category.ListBook = listBook;
            }
            return category;
        }

        public IEnumerable<Book> FetchNextBookPage(int categoryId, int pageNumber)
        {
            var skipItem = (pageNumber - 1)*Constant.MaximunItemsToPaging;
            var listBook =
                _context.Books.Where(b => b.CategoryId == categoryId).OrderBy(p => p.NumberOfViews).Skip(skipItem).Take(
                    Constant.MaximunItemsToPaging).ToList();
            foreach (var book in listBook)
            {
                book.NumberOfLikes = _context.BookLikes.Where(bl => bl.BookId == book.Id).ToList().Count();
                book.NumberOfComments = _context.BookComments.Where(bc => bc.BookId == book.Id).ToList().Count();
                book.Uploader = _context.Users.Where(u => u.Id == book.UploadedBy).FirstOrDefault();
                if (book.Uploader != null)
                {
                    book.UploaderName = book.Uploader.DisplayName;
                    book.UploaderAvartar = book.Uploader.AvatarUrl;
                }
            }
            return listBook;
        }

        #endregion
    }

    public interface ICategoryRepository
    {
        IQueryable<Category> All { get; }
        Category Find(int id);
        void InsertOrUpdate(Category category);
        bool Delete(int id);
        void Save();
        IEnumerable<string> FindCategories(string criteria, int limit);
        IEnumerable<Category> GetAllCategories();
        Category FindCategoryWithAllBooks(int id);
        IEnumerable<Book> FetchNextBookPage(int categoryId, int pageNumber);
    }
}
